﻿using System;
using System.Xml.Linq;

namespace FluentlyXml.Core.Deserialization
{
	/// <summary>
	/// Performs deserialization of objects.  Maintains
	/// an identity cache until disposed, so multiple calls to Deserialize
	/// will return the same instances of objects that were previously
	/// deserialize using the same instance. 
	/// </summary>
	internal class FluentDeserializer : IFluentDeserializer
	{
		private readonly IRuntimeDeserializationConfig _config;

		public FluentDeserializer(IRuntimeDeserializationConfig config)
		{
			_config = config;
		}

		/// <summary>
		/// Deserializes an object.
		/// </summary>
		public T Deserialize<T>(string xml)
		{
			return (T) Deserialize(typeof(T), xml);
		}

		public object Deserialize(Type type, string xml)
		{
			return DeserializeInternal(type, XElement.Parse(xml), new DeserializationContext(this));
		}

		internal object DeserializeInternal(Type type, XElement xml, IDeserializationContext context)
		{
			var deserializer = _config.GetDeserializerFor(type);

			var obj = deserializer.Deserialize(type, xml, context);

			var key = deserializer.GetIdentityFor(obj);

			context.AddObject(key, ref obj);

			return obj;
		}
	}
}